<?php
/*
 * Generates entity classes against MySQL database for each table in the database
 * Handles the following database types with type safety
 *
 * int, varchar, text, boolean, datetime
 *
 * Because boolean is actually a tinyint, tinyint is checked in here but not supported.
 * If you need a small int just use an int. The size shouldnt be a worry these days.
 *
 * blob is also handled but without type safety. It also has issues for large sizes
 * because mysql-php likes to allocate the full amount of space so you can easily
 * fill up your allocated ram with a single insert.
 *
 * Other types will have a method generated for them, which will only check for nullability
 * and then set the value. They will be assumed to be strings when binding.
 *
 */

 /*
  i  	corresponding variable has type integer
  d 	corresponding variable has type double
  s 	corresponding variable has type string
  b 	corresponding variable is a blob and will be sent in packets
 */
 
 
$dbhost = 'localhost';
$dbuser = 'root';
$dbpass = '';
$dbname = '';

$generatevalidators = false;


// Dont touch the below...
$conn = mysql_connect($dbhost, $dbuser, $dbpass) or die ('Error connecting to mysql');
mysql_select_db($dbname);

$temp = mysql_query("SHOW TABLES");

$linebreak   = "\r\n";
$doublespace = "  ";
$quadspace   = "    ";
$septspace   = "      ";
$octspace    = "        ";
$warnings    = array();


while($row = mysql_fetch_array($temp)) {
  $filecontents = '';
  
  $filecontents .= '<?php'.$linebreak;
  $filecontents .= '//////////////////////////////////////////////////////////////'.$linebreak;
  $filecontents .= '// This class generated by a tool on '.date( 'Y-m-d', time() ).' at '.date('H:i:s', time()).' //'.$linebreak;
  $filecontents .= '//////////////////////////////////////////////////////////////'.$linebreak;
  $filecontents .= sprintf('class %s { %s',$row[0],$linebreak);
  
  $temp2 = mysql_query("EXPLAIN ".$row[0]);
  
  $variables = '';
  $getters = '';
  $setters = '';
  $constructor = '';
  $save = '';
  $update = '';
  $values = array();
  $valuesname = array();
  $inserttype = '';
  $primarykey = '';
  $formvalidator = '';
  $fieldvalidators = array();
  $formvalidators = array();
  
  while($row2 = mysql_fetch_array($temp2)) {
	
	$variables .= sprintf('%sprivate $_%s = null;%s',$doublespace,$row2['Field'],$linebreak);
	
	// Dont generate setters for auto_increment values, just getters in the else
	if($row2['Extra'] != 'auto_increment') {
	  $valuesname[] = $row2['Field'];
	  $type = '';
	  $count = 1000000; // set to the default of 1 million
	  $required = 1;
	  $setters .= sprintf('%sfunction set%s($newvalue) {%s',$doublespace,$row2['Field'],$linebreak);
	
	  // If it can be null then add this extra check to allow null values
	  if($row2['Null'] == 'YES') {
	    $setters .= sprintf('%sif(is_null($newvalue)) {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%s$this->_%s = $newvalue;%s',$septspace,$row2['Field'],$linebreak);
		$setters .= sprintf('%sreturn;%s',$septspace,$linebreak);
		$setters .= sprintf('%s}%s',$quadspace,$linebreak);
		$required = 0;
	  }
      else {
        $setters .= sprintf('%sif(is_null($newvalue)) {%s',$quadspace,$linebreak); 
	    $setters .= sprintf('%sthrow new Exception("Value cannot be null - %s");%s}%s',$septspace,$row2['Field'],"\r\n".$quadspace,$linebreak);
	  }
	  
	  // if text
	  if($row2['Type'] == 'text') {
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn $this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);
		
	    $setters .= sprintf('%sif(gettype($newvalue) != "string") {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%sthrow new Exception("Value not string - ".$newvalue);%s}%s',$septspace,"\r\n".$quadspace,$linebreak);
  	    $setters .= sprintf('%s$this->_%s = $newvalue;%s',$quadspace,$row2['Field'],$linebreak);
		$setters .= sprintf('%s}%s',$doublespace,$linebreak);
		$values[] = '?';
		$inserttype .= 's';
		$type = 'anything';
		$htmltype = 'textarea';
	  }
	  else // if int
	  if(strpos($row2['Type'],'int') === 0) {
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn (int)$this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);

		$count = (int)substr($row2['Type'],strpos($row2['Type'],'(')+1,strpos($row2['Type'],')')-strpos($row2['Type'],'(')-1);
	    $setters .= sprintf('%sif(gettype($newvalue) != "integer") {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%sthrow new Exception("Value not integer - ".$newvalue);%s}%s',$septspace,"\r\n".$quadspace,$linebreak);
		
		$setters .= sprintf('%sif(strlen($newvalue) > %s) {%s',$quadspace,$count,$linebreak);
		$setters .= sprintf('%sthrow new Exception("Value size larger then then - %s - ".$newvalue);%s}%s',$septspace,$count,$linebreak.$quadspace,$linebreak);
		$setters .= sprintf('%s$this->_%s = (int)$newvalue;%s',$quadspace,$row2['Field'],$linebreak);
		$setters .= sprintf('%s}%s',$doublespace,$linebreak);
		$values[] = '?';
		$inserttype .= 'i';
		$type = 'integer';
		$htmltype = 'input';
	  }
	  else // if varchar
	  if(strpos($row2['Type'],'varchar') === 0) {
    	$getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn $this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);
	  
	    $count = (int)substr($row2['Type'],strpos($row2['Type'],'(')+1,strpos($row2['Type'],')')-strpos($row2['Type'],'(')-1);
	    $setters .= sprintf('%sif(gettype($newvalue) != "string") {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%sthrow new Exception("Value not string - ".$newvalue);%s}%s',$septspace,"\r\n".$quadspace,$linebreak);
		$setters .= sprintf('%sif(strlen($newvalue) > %s) {%s',$quadspace,$count,$linebreak);
		$setters .= sprintf('%sthrow new Exception("Value size larger then then - %s - ".$newvalue);%s}%s',$septspace,$count,$linebreak.$quadspace,$linebreak);
		$setters .= sprintf('%s$this->_%s = $newvalue;%s',$quadspace,$row2['Field'],$linebreak);
	    $setters .= sprintf('%s}%s',$doublespace,$linebreak);
		$values[] = '?';
		$inserttype .= 's';
		$type = 'anything';
		$htmltype = 'input';
	  }
	  else // if datetime
	  if(strpos($row2['Type'],'datetime') === 0) {
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
    	$getters .= sprintf('%sreturn strtotime($this->_%s);%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);
	  
	    $setters .= sprintf('%sif(gettype($newvalue) != "integer") {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%sthrow new Exception("Value not integer - ".$newvalue);%s}%s',$septspace,"\r\n".$quadspace,$linebreak);		
		$setters .= sprintf('%s$this->_%s = date("Y-m-d H:i:s",(int)$newvalue);%s',$quadspace,$row2['Field'],$linebreak);
	    $setters .= sprintf('%s}%s',$doublespace,$linebreak);
		$values[] = '?';
		$inserttype .= 's';
		$type = 'integer';
		$htmltype = 'input';
	  }
	  else // both bool and tiny int
	  if(strpos($row2['Type'],'tinyint') === 0) {
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn (int)$this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);
	  
	    $count = (int)substr($row2['Type'],strpos($row2['Type'],'(')+1,strpos($row2['Type'],')')-strpos($row2['Type'],'(')-1);
	    $setters .= sprintf('%sif(gettype($newvalue) != "integer") {%s',$quadspace,$linebreak); 
		$setters .= sprintf('%sthrow new Exception("Value not integer - ".$newvalue);%s}%s',$septspace,"\r\n".$quadspace,$linebreak);
		$setters .= sprintf('%sif(strlen($newvalue) > %s) {%s',$quadspace,$count,$linebreak);
		$setters .= sprintf('%sthrow new Exception("Value size larger then then - %s - ".$newvalue);%s}%s',$septspace,$count,$linebreak.$quadspace,$linebreak);
		$setters .= sprintf('%sif($newvalue == false) {%s',$quadspace,$linebreak);
		$setters .= sprintf('%s$newvalue = 0;%s',$septspace,$linebreak);
		$setters .= sprintf('%s}%s',$quadspace,$linebreak);
		$setters .= sprintf('%selse {%s',$quadspace,$linebreak);
		$setters .= sprintf('%s$newvalue = 1;%s',$septspace,$linebreak);
		$setters .= sprintf('%s}%s',$quadspace,$linebreak);
		$setters .= sprintf('%s$this->_%s = (int)$newvalue;%s',$quadspace,$row2['Field'],$linebreak);
	    $setters .= sprintf('%s}%s',$doublespace,$linebreak);
		$values[] = '?';
		$inserttype .= 'i';
		$type = 'integer';
		$htmltype = 'input';
	  }
	  else
	  if(strpos($row2['Type'],'blob') === 0) { 
	    // this actually dosnt work because of the way the me
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn $this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);

        $setters .= sprintf('%s$this->_%s = $newvalue;%s',$quadspace,$row2['Field'],$linebreak);
		$setters .= sprintf('%s}%s',$doublespace,$linebreak);
	    $values[] = '?';
	    $inserttype .= 'b';
		$type = 'file';
		$htmltype = 'file';
	  }
	  else { // just set it and hope the user knows what they are doing
	    $warnings[] = sprintf('Unknown type "%s" may not save correctly. You can ignore this if you know how to handle the database type yourself. CLASSNAME = %s',$row2['Field'],$row[0]);
	    $setters .= sprintf('%s// !!!WARNING!!! Unknown type "%s" may not save correctly. You can ignore this if you know how to handle the database type yourself.%s',$quadspace,$row2['Field'],$linebreak);
		$setters .= sprintf('%s$this->_%s = $newvalue;%s',$quadspace,$row2['Field'],$linebreak);
	    $setters .= sprintf('%s}%s',$doublespace,$linebreak);	    
		$values[] = '?';
		$inserttype .= 's';
		$type = 'anything';
	  }
	  
	}
	else {
	    $getters .= sprintf('%sfunction get%s() {%s',$doublespace,$row2['Field'],$linebreak);
	    $getters .= sprintf('%sreturn $this->_%s;%s}%s',$quadspace,$row2['Field'],"\r\n".$doublespace,$linebreak);
		$values[] = 'NULL';
		$primarykey = $row2['Field'];
	}
	
  }
  
  $partialquery = '';
  $partialvalues = '';
  $partialupdate = '';
  $partialselect = '';
  foreach ($values as $i) {
    $partialquery .= $i.',';
  }
  
  foreach ($valuesname as $i) {
    $partialvalues .= '$this->_'.$i.',';
  }
  
  foreach ($valuesname as $i) {
    $partialupdate .= '`'.$i.'`=?,';
  }
  foreach ($valuesname as $i) {
    $partialselect .= '`'.$i.'`,';
  }
  $partialquery  = rtrim($partialquery ,',');
  $partialupdate = rtrim($partialupdate,',');
  $partialvalues = rtrim($partialvalues,',');
  $partialselect = rtrim($partialselect,',');
  
  $selectquery = sprintf('$query = $db->prepare("SELECT `%s`,%s FROM `%s` WHERE `%s`=? LIMIT 1;");',$primarykey,$partialselect,$row[0],$primarykey);
  $selectquery2 = sprintf('$query->execute(array($id));');

  $insertquery = sprintf('$query = $db->prepare("INSERT INTO `%s` VALUES (%s);");',$row[0],$partialquery);
  $insertquery2 = sprintf('$query->execute(array(%s));',$partialvalues);


  $updatequery = sprintf('$query = $db->prepare("UPDATE `%s` SET %s WHERE `%s`=? LIMIT 1;");',$row[0],$partialupdate,$primarykey,$inserttype,$partialvalues,$primarykey);
  $updatequery2 = sprintf('$query->execute(array(%s,$this->_%s));',$partialvalues,$primarykey);
  $deletequery = sprintf('$query = $db->prepare("DELETE FROM `%s` WHERE `%s`=? LIMIT 1;");',$row[0],$primarykey);
  $deletequery2 = sprintf('$query->execute(array($this->_%s));',$primarykey);
  
  
   
  $filecontents .= sprintf('%s%s',$variables,$linebreak);
  $filecontents .= sprintf('%s',$getters);
  $filecontents .= sprintf('%s',$setters);
  
  // Save function
  $filecontents .= sprintf('%s%sfunction save($db) {%s',$linebreak,$doublespace,$linebreak);
  $filecontents .= sprintf('%sif(is_null($this->_%s)) {%s',$quadspace,$primarykey,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$insertquery,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$insertquery2,$linebreak);
  $filecontents .= sprintf('%s$this->_%s = $db->lastInsertId();%s',$septspace,$primarykey,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%selse {%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$updatequery,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$updatequery2,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$doublespace,$linebreak);
  
  // Delete function
  $filecontents .= sprintf('%s%sfunction delete($db) {%s',$linebreak,$doublespace,$linebreak);
  $filecontents .= sprintf('%sif(is_null($this->_%s)) {%s',$quadspace,$primarykey,$linebreak);
  $filecontents .= sprintf('%sreturn;%s',$septspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%selse {%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$deletequery,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$deletequery2,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$doublespace,$linebreak);
  
  // Select Function
  $selectdo = '';
  foreach ($valuesname as $i) {
    $selectdo .= sprintf('%s$this->_%s = $row_data["%s"];%s',$octspace,$i,$i,$linebreak);
  }
  
  $filecontents .= sprintf('%s%sfunction get($db,$id) {%s',$linebreak,$doublespace,$linebreak);
  $filecontents .= sprintf('%sif(gettype($id) != "integer") {%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%sthrow new Exception("Value not integer");%s',$septspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%selse {%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$selectquery,$linebreak);
  $filecontents .= sprintf('%s%s%s',$septspace,$selectquery2,$linebreak);
  $filecontents .= sprintf('%sforeach ($query->fetchAll() as $row_id => $row_data) {%s',$septspace,$linebreak);
  $filecontents .= sprintf('%s$this->_%s = $row_data["%s"];%s',$octspace,$primarykey,$primarykey,$linebreak);
  $filecontents .= sprintf('%s',$selectdo);
  $filecontents .= sprintf('%s}%s',$septspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$quadspace,$linebreak);
  $filecontents .= sprintf('%s}%s',$doublespace,$linebreak);
  

  $filecontents .= sprintf('}%s',$linebreak);
  $filecontents .= '?>';
  
  echo '<pre>'.htmlspecialchars($filecontents).'</pre>';

}

mysql_close($conn);

echo "<h2>Warnings</h2>";
echo '<pre>';
print_r($warnings);
echo '</pre>';

?>